/* MyMAM - Open Source Digital Media Asset Management. * http://www.mymam.net * * Copyright 2013, MyMAM contributors as indicated by the @author tag. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.mymam.server.test; import javax.security.auth.Subject; import javax.security.auth.callback.*; import javax.security.auth.login.AppConfigurationEntry; import javax.security.auth.login.Configuration; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * Provides a {@link LoginContext} for use by unit tests. * * <p/> * This is based on Stephen Coy's * <a href="https://github.com/sfcoy/demos.git">Arquillian Security Demo</a>, * but uses database authentication instead of UsersRoles properties files. * * <p/> * See also: * <ul> * <li>https://community.jboss.org/wiki/TestingSecuredEJBsOnJBossAS71xWithArquillian</li> * <li>http://stackoverflow.com/questions/11386651</li> * </ul> * * @author fstab */ public class JBossLoginContextFactory { static class NamePasswordCallbackHandler implements CallbackHandler { private final String username; private final String password; private NamePasswordCallbackHandler(String username, String password) { this.username = username; this.password = password; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback current : callbacks) { if (current instanceof NameCallback) { ((NameCallback) current).setName(username); } else if (current instanceof PasswordCallback) { ((PasswordCallback) current).setPassword(password.toCharArray()); } else { throw new UnsupportedCallbackException(current); } } } } static class JBossJaasConfiguration extends Configuration { private final String configurationName; JBossJaasConfiguration(String configurationName) { this.configurationName = configurationName; } @Override public AppConfigurationEntry[] getAppConfigurationEntry(String name) { if (!configurationName.equals(name)) { throw new IllegalArgumentException("Unexpected configuration name '" + name + "'"); } return new AppConfigurationEntry[] { createDatabaseModuleConfigEntry(), createClientLoginModuleConfigEntry(), }; } /** * The {@link org.jboss.security.auth.spi.DatabaseServerLoginModule} creates the * association between users and roles. * * @return */ private AppConfigurationEntry createDatabaseModuleConfigEntry() { Map options = new HashMap(); options.put("dsJndiName", "java:jboss/jdbc/mymamDS"); options.put("principalsQuery", "select hashedpassword from user_table where username=?"); options.put("rolesQuery", "select name, 'Roles' from role join role_user_table on role.id = role_user_table.roles_id join user_table on user_table.id = role_user_table.users_id where user_table.username=?"); options.put("hashAlgorithm", "MD5"); options.put("hashEncoding", "base64"); return new AppConfigurationEntry("org.jboss.security.auth.spi.DatabaseServerLoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options); } /** * The {@link org.jboss.security.ClientLoginModule} associates the user credentials with the * {@link org.jboss.security.SecurityContext} where the JBoss security runtime can find it. * * @return */ private AppConfigurationEntry createClientLoginModuleConfigEntry() { Map<String, String> options = new HashMap<String, String>(); options.put("multi-threaded", "true"); options.put("restore-login-identity", "true"); return new AppConfigurationEntry("org.jboss.security.ClientLoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options); } } /** * Obtain a LoginContext configured for use with the ClientLoginModule. * * @return the configured LoginContext. */ public static LoginContext createLoginContext(final String username, final String password) throws LoginException { final String configurationName = "Arquillian Testing"; CallbackHandler cbh = new JBossLoginContextFactory.NamePasswordCallbackHandler(username, password); Configuration config = new JBossJaasConfiguration(configurationName); return new LoginContext(configurationName, new Subject(), cbh, config); } }